package panda.query.tree;

import java.util.List;

import panda.query.aggr.AggregateFn;
import panda.query.aggr.IntAvgFn;
import panda.query.scan.GroupByScanner;
import panda.query.scan.Scanner;
import panda.query.struct.Attribute;
import panda.record.Schema;
import panda.transaction.Transaction;

public class GroupByNode implements QueryTreeNode {
	QueryTreeNode n;
	List<Attribute> attrs;
	List<AggregateFn> aggrFn;
	Schema schema = new Schema();
	Transaction tx;
	
	public GroupByNode(QueryTreeNode n, List<Attribute> attrs, List<AggregateFn> aggrFn, Transaction tx) {
		this.n = n;
		this.attrs = attrs;
		this.aggrFn = aggrFn;
		this.tx = tx;
		for (int i = 0; i < attrs.size(); i++)
			schema.addAttribute(attrs.get(i), n.getSchema());
		for (int i = 0; i < aggrFn.size(); i++) {
			if (aggrFn.get(i) instanceof IntAvgFn)
				schema.addFloatAttr(aggrFn.get(i).getAttribute());
			else
				schema.addIntAttr(aggrFn.get(i).getAttribute());
		}
	}

	public Scanner open() {
		QueryTreeNode sn;
		if (attrs.size() != 0) 
			sn = new SortNode(n, attrs, tx);
		else
			sn = n;
		return new GroupByScanner(sn.open(), attrs, aggrFn);
	}
	
	public int blockAccessed() {
		return n.blockAccessed();
	}

	public int distinctSize(Attribute attr) {
		if (n.getSchema().hasAttribute(attr))
			return n.distinctSize(attr);
		else
			return outputSize();
	}

	public int outputSize() {
		int temp = 1;
		for (int i = 0; i < attrs.size(); i++)
			temp *= n.distinctSize(attrs.get(i));
		return temp;
	}

	public Schema getSchema() {
		return schema;
	}

}
